/**
 * @file rtk_thread.h
 * @author LokLiang (lokliang@163.com)
 * @brief
 * @version 0.1
 * @date 2023-05-01
 *
 * @copyright Copyright (c) 2023
 *
 */

#ifndef __RTK_THREAD_H__
#define __RTK_THREAD_H__

#include "rtk_def.h"
#include <stdbool.h>

#ifdef __cplusplus
extern "C"
{
#endif /* #ifdef __cplusplus */

typedef struct
{
    rtk_hdl_t hdl;
} rtk_thread_t;

/*************************************************************************
** 线程创建和删除
*************************************************************************/
rtk_thread_t *rtk_thread_init(rtk_thread_t *thread_handle, // 线程句柄（若取值为空则由内部自动分配，不允许使用局部变量）
                              const char *name,            // 线程名
                              void (*entry)(void *arg),    // 线程入口地址
                              void *arg,                   // 线程入口参数
                              void *stack_base,            // 栈内存地址
                              size_t stack_size,           // 栈大小（字节）
                              rtk_prior_t priority,        // 优先级（0 为最低，CONFIG_RTK_MAX_PRIORITY 为最高。若输入为负值则表示优先级为 (CONFIG_RTK_MAX_PRIORITY + 1 + priority)）
                              u8_t slice_ticks             // 被轮换的时间（值为 0 时不被轮换）
);

rtk_thread_t *rtk_thread_create(rtk_thread_t *thread_handle, // 线程句柄（若取值为空则由内部自动分配，不允许使用局部变量）
                                const char *name,            // 线程名
                                void (*entry)(void *arg),    // 线程入口地址
                                void *arg,                   // 线程入口参数
                                size_t stack_size,           // 栈大小（字节）
                                rtk_prior_t priority,        // 优先级（0 为最低，CONFIG_RTK_MAX_PRIORITY 为最高。若输入为负值则表示优先级为 (CONFIG_RTK_MAX_PRIORITY + 1 + priority)）
                                u8_t slice_ticks             // 被轮换的时间（值为 0 时不被轮换）
);

rtk_err_t rtk_thread_delete(rtk_thread_t *thread_handle); // 删除指定的线程（线程曾经申请过的内存将被自动回收）。

/*************************************************************************
** 设置线程状态：对象为本线程
*************************************************************************/
void rtk_thread_sleep(rtk_tick_t ticks);
void rtk_thread_sleep_until(rtk_tick_t ticks); // 从最后一次唤醒的时间算起，延时多少个系统节拍后再执行本任务（固定周期的延时）。返回 !RTK_OK 表示没有通过 rtk_tick_start() 启动定时器服务
void rtk_thread_sleep_time(size_t hours, size_t minute, size_t second, size_t milli);

void rtk_thread_yield(void);   // 释放当前 CPU 使用权（下个相同等级的线程将得到 CPU 使用权），轮换计时被重置。注意当前线程正在使用互斥量时无效
void rtk_thread_suspend(void); // 挂起当前线程

/*************************************************************************
** 设置线程状态。线程和中断都可使用
*************************************************************************/
rtk_err_t rtk_thread_set_suspend(rtk_thread_t *thread_handle);                        // 挂起线程
rtk_err_t rtk_thread_resume(rtk_thread_t *thread_handle);                             // 使线程的唤醒计数器的值递增 1 然后把线程从挂起状态中恢复一次。用于中断与线程之间同步。（只有线程正在处于挂起状态下才会被唤醒）
rtk_err_t rtk_thread_set_priority(rtk_thread_t *thread_handle, rtk_prior_t priority); // 设置线程优先级（0 为最低，CONFIG_RTK_MAX_PRIORITY 为最高。若输入为负值则表示 优先级 = (CONFIG_RTK_MAX_PRIORITY + 1 + priority)）。
rtk_err_t rtk_thread_set_slice_ticks(rtk_thread_t *thread_handle, u8_t slice_ticks);  // 更改被轮换的生存周期（值为 0 时不被轮换）。

void rtk_thread_set_errno(int errno);
int  rtk_thread_get_errno(void);

/*************************************************************************
** 获取务状和态。线程和中断都可用
*************************************************************************/
void               rtk_thread_list_reset(void);
rtk_thread_t      *rtk_thread_list_next(void);                               // 列出下个线程
rtk_thread_t      *rtk_thread_get_self(void);                                // 获取当前运行的线程
rtk_thread_state_t rtk_thread_get_state(rtk_thread_t *thread_handle);        // 返回线程状态
char              *rtk_thread_get_name(rtk_thread_t *thread_handle);         // 获取线程名
u8_t               rtk_thread_get_slice_ticks(rtk_thread_t *thread_handle);  // 获取线程当前的轮换时间
rtk_prior_t        rtk_thread_get_priority(rtk_thread_t *thread_handle);     // 获取线程当前的优先级
void              *rtk_thread_stack_base(rtk_thread_t *thread_handle);       // 获取线程的栈地址
size_t             rtk_thread_stack_size(rtk_thread_t *thread_handle);       // 获取线程的栈大小
int                rtk_thread_stack_used_size(rtk_thread_t *thread_handle);  // 根据线程的使用痕迹，计算使用过最大的栈内存。用穿返回 -1
int                rtk_thread_stack_empty_size(rtk_thread_t *thread_handle); // 根据线程的使用痕迹，计算剩余最小的栈内存。用穿返回 -1
bool               rtk_thread_is_valid(rtk_thread_t *thread_handle);         // 查询线程句柄是否有效

#ifdef __cplusplus
} /* extern "C" */
#endif /* #ifdef __cplusplus */

#endif
